#include "threadPool.h"

char buffer[4096] = {0};
char buffer2[4096] = {0};
int recvn(int sockfd, void *buf, int length)
{                          // 自己实现MSG_WAITALL
    int total = 0;         // 已经接受的长度
    char *p = (char *)buf; // char的单位为1
    while (total < length)
    { // 断点重传
        ssize_t sret = recv(sockfd, p + total, length - total, 0);
        total = total + sret;
    }
    return 0;
}
int recvfile(int sockfd)
{
    train_t train;
    recvn(sockfd, &train.length, sizeof(train.length)); // 接收文件名长度，一个int整数,即读取前的四个字节的内容为文件名的长度
    recvn(sockfd, train.data, train.length);            // 接收文件名
    char filename[1024] = {0};
    memcpy(filename, train.data, train.length);

    int fd = open(filename, O_RDWR | O_CREAT, 0600); // 创建该文件
    off_t filesize;

    recvn(sockfd, &train.length, sizeof(train.length));
    recvn(sockfd, &train.data, train.length);
    memcpy(&filesize, train.data, train.length);
    ftruncate(fd, filesize);
    char *p = (char *)mmap(NULL, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    recvn(sockfd, p, filesize);
    munmap(p, filesize);
    return 0;
}
void *threadFunc(void *arg)
{
    threadPool_t *pthreadPool = (threadPool_t *)arg;
    while (1)
    {
        // 接受任务
        pthread_mutex_lock(&pthreadPool->taskQueue.mutex);
        while (pthreadPool->taskQueue.queueSize <= 0)
        {
            pthread_cond_wait(&pthreadPool->taskQueue.cond, &pthreadPool->taskQueue.mutex);
        }
        int netfd = pthreadPool->taskQueue.pFront->netfd;
        deQueue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->taskQueue.mutex);
        // 完成任务
        char absolutePath[1024] = "/home/joey/netdisk_-one-two/12_NetDisk/server";
        /*char absolutePath[1024] = {0};
        char currentPath[1024] = {0};
        strcpy(currentPath, getcwd(absolutePath, sizeof(absolutePath)));
        printf("absolutePath = %s\n", absolutePath);
        printf("currentPath = %s\n", currentPath);*/
        char PATH[1024] = {0};
        int flag_cd = 1;
        int flag_ls = 1;
        int flag_pwd = 1;
        int flag_mkdir = 1;
        int flag_rmdir = 1;
        int flag_remove = 1;
        int flag_puts = 1;
        int flag_gets = 1;
        int abslen = strlen(absolutePath);
        //printf("abslength = %d\n", abslen);
        while (1){
            char relativePath[256] = {0};
            char command[256] = {0};
            char cd[] = "cd";
            char ls[] = "ls";
            char pwd[] = "pwd";
            char makedir[] = "mkdir";
            char removedir[] = "rmdir";
            char removefile[] = "remove";
            char puts[] = "puts";
            char gets[] = "gets";

            bzero(buffer,sizeof(buffer));
            recv(netfd, buffer, sizeof(buffer), 0);
            //printf("buffer = %s\n", buffer);
            int i;
            for (i = 0; buffer[i] != '\n' && buffer[i] != ' ' && buffer[i] != '\0'; i++)
            {
                /*if (buffer[i] == ' '){
                    break;
                }
                if (buffer[i] == '\n'){
                    break;
                }
                if (buffer[i] == '\0'){
                    break;
                }*/
                command[i] = buffer[i];
            }
            //printf("command = %s\n", command);
            int j = i + 1;
            int k = 0;
            for (j, k; buffer[j] != '\0'; j++, k++){
                if (buffer[i] == '\n')
                {
                    break;
                }
                relativePath[k] = buffer[j];
            }
            //printf("relativePath = %s\n", relativePath);
            flag_ls = strcmp(command, ls);
            flag_pwd = strcmp(command, pwd);
            flag_cd = strcmp(command, cd);
            flag_mkdir = strcmp(command, makedir);
            flag_rmdir = strcmp(command, removedir);
            flag_remove = strcmp(command, removefile);
            flag_puts = strcmp(command, puts);
            flag_gets = strcmp(command, gets);

            char Path[1024] = {0}; 

            strcpy(Path, absolutePath);// Path是此时服务端的路径
            //printf("absolutePath = %s\n", absolutePath);
            node_t *head = NULL;
            node_t *tail = NULL;
            char absPath[1024] = {0};
            //test..
            if (flag_cd == 0)
            {
                sprintf(absolutePath, "%s/%s", absolutePath, relativePath);
                pushStack(&head, &tail, Path);
                if (relativePath[0] == '.' && relativePath[1] == '.')
                {
                    pop(&head, &tail);
                    node_t *pCur = head;
                    sprintf(absPath, "%s", pCur->pathname);
                    pCur = pCur->Next;
                    sprintf(absPath, "%s%s", absPath, pCur->pathname);
                    pCur = pCur->Next;
                    while (pCur != NULL)
                    {
                        sprintf(absPath, "%s/%s", absPath, pCur->pathname);
                        pCur = pCur->Next;
                    }
                    int len = strlen(absPath);
                    strcpy(absolutePath, absPath);
                    NETDISK_LOG_INFO(LOG_INFO, absolutePath);
                    char PATH[1024] = {0};
                    for(int i = abslen, j = 0; absolutePath[i] != '\0'; i++,j++){
                        PATH[j] = absolutePath[i];
                    }
                    //printf("PATH = %s\n", PATH);
                    //send(netfd, absolutePath, sizeof(absolutePath), 0);
                    send(netfd, PATH, sizeof(PATH), 0);
                    flag_cd = 1;
                }
                else{
                    // relativePath = dir1

                    push(&head, &tail, relativePath);
                    node_t *pCur = head;
                    sprintf(absPath, "%s", pCur->pathname);
                    pCur = pCur->Next;
                    sprintf(absPath,"%s%s",absPath,pCur->pathname);
                    pCur = pCur->Next;
                    while (pCur != NULL)
                    {
                        sprintf(absPath, "%s/%s", absPath, pCur->pathname);
                        pCur = pCur->Next;
                    }
                    int len = strlen(absPath);
                    strcpy(absolutePath, absPath);
                    absolutePath[len - 1] = '\0';
                    NETDISK_LOG_INFO(LOG_INFO, absolutePath);
                    
                    for(int i = abslen, j = 0; absolutePath[i] != '\0' ;i++, j++){
                        PATH[j] = absolutePath[i];
                    }
                    //printf("PATH = %s\n", PATH);
                    //send(netfd, absolutePath, sizeof(absolutePath), 0);
                    send(netfd, PATH, sizeof(PATH), 0);
                    flag_cd = 1;
                }
                
            }
            else if (flag_ls == 0)
            {  
                //printf("ls start\n");
                char apath[1024] = {0};
                char dirname[1024] = {0};
                char dir[1024] = {0};
                strcpy(apath, absolutePath);
                DIR* curDir;
                struct dirent* curItem;
                // 打开目录
                if((curDir = opendir(apath)) == NULL){
                    ERROR_CHECK(-1, NULL, "opendir");
                }
                else {
                    // 读取目录并显示目录名
                    curItem = readdir(curDir);
                    strcpy(dirname, curItem->d_name);
                    while((curItem = readdir(curDir))){
                        sprintf(dirname, "%s %s", dirname, curItem->d_name);
                    }
                    //printf("dirname = %s\n", dirname);
                    int ret = send(netfd, dirname, sizeof(dirname), 0);
                    ERROR_CHECK(ret, -1, "send");
                    flag_ls = 1;
                }
            }
            // mkdir dir1
            else if (flag_mkdir == 0)
            {   
                char apath[1024] = {0};
                strcpy(apath, absolutePath);
                sprintf(apath, "%s/%s", apath, relativePath);
                
                int len = strlen(apath);
                apath[len-1] = '\0';
                int ret = mkdir(apath, (mode_t)0777);
                ERROR_CHECK(ret, -1, "mkdir");
                flag_mkdir = 1;
                char* right = "success";
                char* fail = "fail";
                if(ret == 0){
                    send(netfd, right, sizeof(right), 0); 
                }
                if(ret == -1){
                    send(netfd, fail, sizeof(fail), 0);
                }
            }
            else if (flag_rmdir == 0){
                char apath[1024] = {0};
                strcpy(apath, absolutePath);
                sprintf(apath, "%s/%s", apath, relativePath);
                int len = strlen(apath);
                apath[len-1] = '\0';
                int ret = rmdir(apath);
                ERROR_CHECK(ret, -1, "rmdir");
                flag_rmdir = 1;
                char* right = "success";
                char* fail = "fail";
                if(ret == 0){
                    send(netfd, right, sizeof(right), 0); 
                }
                if(ret == -1){
                    send(netfd, fail, sizeof(fail), 0);
                }
            }
            // remove
            else if (flag_remove == 0){
                //printf("remove start\n");
                char apath[1024] = {0};
                strcpy(apath, absolutePath);
                sprintf(apath, "%s/%s", apath, relativePath);
                int len = strlen(apath);
                apath[len-1] = '\0';
                //test
                //printf("\n-->apath = %s\n",apath);
                int ret = unlink(apath);
                flag_remove = 1;
                char* right = "success";
                char* fail = "fail";
                if(ret == 0){
                    send(netfd, right, sizeof(right), 0); 
                }
                if(ret == -1){
                    send(netfd, fail, sizeof(fail), 0);
                }
            }
            // puts
            else if (flag_puts == 0)
            {
                recvfile(netfd);
                flag_puts = 1;
            }
            // gets
            else if (flag_gets == 0)
            {
                transfile(netfd);
                flag_gets = 1;
            }
            // pwd
            else if (flag_pwd == 0)
            {
                //send(netfd, absolutePath, sizeof(absolutePath), 0);
                send(netfd, PATH, sizeof(PATH), 0);
                flag_pwd = 1;
            }
        }
    }
}
int makeWorker(threadPool_t *pthreadPool)
{
    for (int i = 0; i < pthreadPool->workerNum; i++)
    {
        pthread_create(&pthreadPool->tidArr[i], NULL, threadFunc, pthreadPool);
    }
    return 0;
}